import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:word_range_client/pojo/Result.dart';
import 'package:word_range_client/viewModels/UserViewModel.dart';

import '../pojo/dto/PageDto.dart';

class HttpService {
  final String _baseUrl;

  HttpService(this._baseUrl);

  // Future<void> refreshJwt() async {
  //   final prefs = await SharedPreferences.getInstance();
  //   var phone = prefs.getString("phone");
  //   var password = prefs.getString("password");
  //   if(phone == null || password == null){
  //     return;
  //   }
  //   UserRepository.login(phone, password);
  // }

  Future<Result> post(String path, Map<String, dynamic> body, {Map<String, String>? headers}) async {
    int maxRetry = 1;   // 最大重试次数
    int attempt = 0;
    late http.Response response;

    while (attempt <= maxRetry) {
      // 准备基础请求参数
      var url = Uri.parse('$_baseUrl/$path');
      // 过滤掉值为空的键值对
      var filteredBody = Map<String, dynamic>.from(body)..removeWhere((key, value) => value == null || value == '');
      var jsonBody = jsonEncode(filteredBody);
      final prefs = await SharedPreferences.getInstance();

      // 处理请求头
      final defaultHeaders = Map<String, String>.from(headers ?? {});
      defaultHeaders.putIfAbsent('Content-Type', () => 'application/json');

      // 添加 Token
      var token = prefs.getString("token");
      if (token != null && !defaultHeaders.containsKey("JWT")) {
        defaultHeaders["JWT"] = token;
      }

      print("Attempt $attempt: URL:$url; body:$jsonBody; header:$defaultHeaders");

      // 发送请求
      response = await http.post(url, body: jsonBody, headers: defaultHeaders);

      // 处理 403 需要重试的情况
      if (response.statusCode == 403 && attempt < maxRetry) {
        final phone = prefs.getString("phone");
        final password = prefs.getString("password");

        if (phone == null || password == null) {
          // TODO: 跳回欢迎页，清空数据
          throw Exception('需要重新登录: 缺少用户凭证');
        }

        try {
          print("尝试自动重新登录...");
          UserViewModel userViewModel = UserViewModel();
          await userViewModel.login(phone, password);
          attempt++;
          continue;
        } catch (e) {
          throw Exception('自动登录失败: $e');
        }
      }

      // 处理正常响应
      if (response.statusCode == 200) {
        final utf8Decoder = Utf8Decoder();
        return Result.fromJson(jsonDecode(utf8Decoder.convert(response.bodyBytes)));
      }

      // 其他异常状态码
      throw Exception('网络错误: ${response.statusCode}');
    }

    // 重试后仍失败
    throw Exception('请求失败: 重试后仍返回 403 状态码');
  }

  Future<Result> put(String path, Map<String, dynamic> body, {Map<String, String>? headers}) async {
    int maxRetry = 1;   // 最大重试次数
    int attempt = 0;
    late http.Response response;

    while (attempt <= maxRetry) {
      // 准备基础请求参数
      var url = Uri.parse('$_baseUrl/$path');
      // 过滤掉值为空的键值对
      var filteredBody = Map<String, dynamic>.from(body)..removeWhere((key, value) => value == null || value == '');
      var jsonBody = jsonEncode(filteredBody);
      final prefs = await SharedPreferences.getInstance();

      // 处理请求头
      final defaultHeaders = Map<String, String>.from(headers ?? {});
      defaultHeaders.putIfAbsent('Content-Type', () => 'application/json');

      // 添加 Token
      var token = prefs.getString("token");
      if (token != null && !defaultHeaders.containsKey("JWT")) {
        defaultHeaders["JWT"] = token;
      }

      print("Attempt $attempt: URL:$url; body:$jsonBody; header:$defaultHeaders");

      // 发送请求
      response = await http.put(url, body: jsonBody, headers: defaultHeaders);

      // 处理 403 需要重试的情况
      if (response.statusCode == 403 && attempt < maxRetry) {
        final phone = prefs.getString("phone");
        final password = prefs.getString("password");

        if (phone == null || password == null) {
          throw Exception('需要重新登录: 缺少用户凭证');
        }

        try {
          print("尝试自动重新登录...");
          UserViewModel userViewModel = UserViewModel();
          await userViewModel.login(phone, password);
          attempt++;
          continue;
        } catch (e) {
          throw Exception('自动登录失败: $e');
        }
      }

      // 处理正常响应
      if (response.statusCode == 200) {
        final utf8Decoder = Utf8Decoder();
        return Result.fromJson(jsonDecode(utf8Decoder.convert(response.bodyBytes)));
      }

      // 其他异常状态码
      throw Exception('网络错误: ${response.statusCode}');
    }

    // 重试后仍失败
    throw Exception('请求失败: 重试后仍返回 403 状态码');
  }

  Future<Result> get(String path, {Map<String, dynamic>? queryParameters, Map<String, String>? headers}) async {
    int maxRetry = 1;
    int attempt = 0;
    late http.Response response;

    while (attempt <= maxRetry) {
      // 准备基础请求参数
      final prefs = await SharedPreferences.getInstance();

      print("queryParameters:$queryParameters");
      // 构建 URL（每次循环重新构建确保参数正确）
      final Uri url = queryParameters != null
          ? Uri.parse('$_baseUrl/$path').replace(queryParameters: queryParameters.map((key, value) => MapEntry(key, value?.toString())))
          : Uri.parse('$_baseUrl/$path');

      // 处理请求头
      final defaultHeaders = Map<String, String>.from(headers ?? {});

      // 添加 Token（每次循环重新获取最新 token）
      var token = prefs.getString("token");
      if (token != null && !defaultHeaders.containsKey("JWT")) {
        defaultHeaders["JWT"] = token;
      }

      print("Attempt $attempt: URL:$url; headers:$defaultHeaders");

      // 发送请求
      response = await http.get(url, headers: defaultHeaders);
      // print(response.body);
      // 处理 403 需要重试的情况
      if (response.statusCode == 403 && attempt < maxRetry) {
        final phone = prefs.getString("phone");
        final password = prefs.getString("password");

        if (phone == null || password == null) {
          throw Exception('需要重新登录: 缺少用户凭证');
        }

        try {
          print("尝试自动重新登录...");
          UserViewModel userViewModel = UserViewModel();
          await userViewModel.login(phone, password);
          attempt++;
          continue;
        } catch (e) {
          throw Exception('自动登录失败: $e');
        }
      }

      // 处理正常响应
      if (response.statusCode == 200) {
        final utf8Decoder = Utf8Decoder();
        return Result.fromJson(jsonDecode(utf8Decoder.convert(response.bodyBytes)));
      }

      // 其他异常状态码
      throw Exception('网络错误: ${response.statusCode}');
    }

    // 重试后仍失败
    throw Exception('请求失败: 重试后仍返回 403 状态码');
  }

  Future<Result> delete(String path, {Map<String, dynamic>? queryParameters, Map<String, String>? headers}) async {
    int maxRetry = 1;
    int attempt = 0;
    late http.Response response;

    while (attempt <= maxRetry) {
      // 准备基础请求参数
      final prefs = await SharedPreferences.getInstance();

      // 构建 URL（每次循环重新构建确保参数正确）
      final Uri url = queryParameters != null
          ? Uri.parse('$_baseUrl/$path').replace(queryParameters: queryParameters.map((key, value) => MapEntry(key, value?.toString())))
          : Uri.parse('$_baseUrl/$path');

      // 处理请求头
      final defaultHeaders = Map<String, String>.from(headers ?? {});

      // 添加 Token（每次循环重新获取最新 token）
      var token = prefs.getString("token");
      if (token != null && !defaultHeaders.containsKey("JWT")) {
        defaultHeaders["JWT"] = token;
      }

      print("Attempt $attempt: URL:$url; headers:$defaultHeaders");

      // 发送请求
      response = await http.delete(url, headers: defaultHeaders);

      // 处理 403 需要重试的情况
      if (response.statusCode == 403 && attempt < maxRetry) {
        final phone = prefs.getString("phone");
        final password = prefs.getString("password");

        if (phone == null || password == null) {
          throw Exception('需要重新登录: 缺少用户凭证');
        }

        try {
          print("尝试自动重新登录...");
          UserViewModel userViewModel = UserViewModel();
          await userViewModel.login(phone, password);
          attempt++;
          continue;
        } catch (e) {
          throw Exception('自动登录失败: $e');
        }
      }

      // 处理正常响应
      if (response.statusCode == 200) {
        final utf8Decoder = Utf8Decoder();
        return Result.fromJson(jsonDecode(utf8Decoder.convert(response.bodyBytes)));
      }

      // 其他异常状态码
      throw Exception('网络错误: ${response.statusCode}');
    }

    // 重试后仍失败
    throw Exception('请求失败: 重试后仍返回 403 状态码');
  }

  Future<PageDto> getPageDto(String path, {Map<String, dynamic>? queryParameters, Map<String, String>? headers}) async {
    int maxRetry = 1; // 最大重试次数
    int attempt = 0; // 当前尝试次数
    late http.Response response;

    while (attempt <= maxRetry) {
      // 准备基础请求参数
      final prefs = await SharedPreferences.getInstance();

      // 构建 URL（每次循环重新构建确保参数正确）
      final Uri url = queryParameters != null
          ? Uri.parse('$_baseUrl/$path').replace(
        queryParameters: queryParameters.map((key, value) => MapEntry(key, value?.toString())),
      )
          : Uri.parse('$_baseUrl/$path');

      // 处理请求头
      final defaultHeaders = Map<String, String>.from(headers ?? {});


      // 添加 Token（每次循环重新获取最新 token）
      var token = prefs.getString("token");
      if (token != null && !defaultHeaders.containsKey("JWT")) {
        defaultHeaders["JWT"] = token;
      }


      print("Attempt $attempt: URL:$url; headers:$defaultHeaders");

      // 发送请求
      response = await http.get(url, headers: defaultHeaders);

      // 处理 403 需要重试的情况
      if (response.statusCode == 403 && attempt < maxRetry) {
        final phone = prefs.getString("phone");
        final password = prefs.getString("password");

        if (phone == null || password == null) {
          throw Exception('需要重新登录: 缺少用户凭证');
        }

        try {
          print("尝试自动重新登录...");
          UserViewModel userViewModel = UserViewModel();
          await userViewModel.login(phone, password);
          attempt++;
          continue;
        } catch (e) {
          throw Exception('自动登录失败: $e');
        }
      }

      // 处理正常响应
      if (response.statusCode == 200) {
        final utf8Decoder = Utf8Decoder();
        final jsonResponse = jsonDecode(utf8Decoder.convert(response.bodyBytes));
        return PageDto.fromJson(jsonResponse); // 将 JSON 转换为 PageDto
      }

      // 其他异常状态码
      throw Exception('网络错误: ${response.statusCode}');
    }

    // 重试后仍失败
    throw Exception('请求失败: 重试后仍返回 403 状态码');
  }

}